package com.xm.common.service.impl;

import com.xm.common.entity.dto.HistoryData;
import com.xm.common.entity.vo.request.MonitorQueryParam;
import com.xm.common.entity.vo.response.MonitorResponse;
import com.xm.common.mapper.HistoryMapper;
import com.xm.common.service.HistoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;

@Service
@RequiredArgsConstructor
public class HistoryServiceImpl implements HistoryService {
    private final HistoryMapper historyMapper;

    @Override
    public MonitorResponse queryData(MonitorQueryParam param) {
        validateParam(param);
        String interval = determineInterval(param.getStart(), param.getEnd());
        String tableName = buildTableName(param.getStatType(), interval);

        List<HistoryData> dataList = historyMapper.selectDynamicData(
                tableName,
                param.getClientId(),
                toEpochMillis(param.getStart()),
                toEpochMillis(param.getEnd()),
                param.getMetricType()
        );

//        return dataList.stream()
//                .map(data -> convertToResponse(data, param.getMetricType(), tableName.split("_")[2]))
//                .toList();
        return convertToResponse(dataList, param.getMetricType(), tableName.split("_")[2], param.getClientId());
    }

    public String determineInterval(LocalDateTime start, LocalDateTime end) {
        Duration duration = Duration.between(start, end);
        long minutes = duration.toMinutes();

        if (minutes < 1) {
            throw new IllegalArgumentException("时间范围不能小于1分钟");
        }
        if (minutes > 30 * 24 * 60) {
            throw new IllegalArgumentException("时间范围超过30天");
        }

        if (minutes <= 60) {
            return "1m";
        } else if (minutes <= 6 * 60) {
            return "5m";
        } else if (minutes <= 12 * 60) {
            return "10m";
        } else if (minutes <= 24 * 60) {
            return "20m";
        } else if (minutes <= 3 * 24 * 60) {
            return "60m";
        } else if (minutes <= 7 * 24 * 60) {
            return "120m";
        } else if (minutes <= 14 * 24 * 60) {
            return "360m";
        } else {
            return "720m";
        }
    }

    private void validateParam(MonitorQueryParam param) {
        if (param.getEnd().isBefore(param.getStart())) {
            throw new IllegalArgumentException("结束时间不能早于开始时间");
        }
    }

    private LocalDateTime convertToLocalDateTime(long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
    }

    private MonitorResponse convertToResponse(List<HistoryData> data, String metricType, String period, int clientId) {
        MonitorResponse response = new MonitorResponse();
        response.setClientId(clientId);
        response.setMetricType(metricType);
        switch (period) {
            case "1m":
                response.setPeriod("1分钟");
                break;
            case "5m":
                response.setPeriod("5分钟");
                break;
            case "10m":
                response.setPeriod("10分钟");
                break;
            case "20m":
                response.setPeriod("20分钟");
                break;
            case "60m":
                response.setPeriod("1小时");
                break;
            case "120m":
                response.setPeriod("2小时");
                break;
            case "360m":
                response.setPeriod("6小时");
                break;
            case "720m":
                response.setPeriod("12小时");
                break;
        }

        switch (metricType) {
            case "CPU":
                List<MonitorResponse.CommonData> cpuData = data.stream()
                        .map(d -> new MonitorResponse.CommonData(convertToLocalDateTime(d.getTimestamp()), d.getCpuUsage() * 100))
                        .toList();
                response.setCommonData(cpuData);
                break;
            case "MEMORY":
                List<MonitorResponse.CommonData> memoryData = data.stream()
                        .map(d -> new MonitorResponse.CommonData(convertToLocalDateTime(d.getTimestamp()), d.getMemoryUsage()))
                        .toList();
                response.setCommonData(memoryData);
                break;
            case "DISK":
                List<MonitorResponse.CommonData> disk = data.stream()
                        .map(d -> new MonitorResponse.CommonData(convertToLocalDateTime(d.getTimestamp()), d.getDiskUsage()))
                        .toList();
                response.setCommonData(disk);
                break;
            case "DISK-IO":
                List<MonitorResponse.DiskData> diskIo = data.stream()
                        .map(d -> new MonitorResponse.DiskData(convertToLocalDateTime(d.getTimestamp()), d.getDiskRead(), d.getDiskWrite()))
                        .toList();
                response.setDisks(diskIo);
                break;
            case "NETWORK":
                List<MonitorResponse.NetworkData> network = data.stream()
                        .map(d -> new MonitorResponse.NetworkData(convertToLocalDateTime(d.getTimestamp()), d.getNetworkUpload(), d.getNetworkDownload()))
                        .toList();
                response.setNetwork(network);
                break;
        }
        return response;
    }

    private String buildTableName(String statType, String interval) {
        return "history_" + statType.toLowerCase() + "_" + interval;
    }

    private long toEpochMillis(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }
}
